<?php
namespace aop\core;

trait MethodDocumentInterpreterTrait {

    private function _fetchMethodReflectionInfo($concret, $methodName) {
        $methodReflectionData = ['document' => '', 'param_name_list' => [], 'reflection' => NULL];

        try {
            $methodReflection = new \ReflectionMethod($concret, $methodName);
            $methodReflectionData['reflection'] = $methodReflection;
            $methodReflectionData['document'] = $methodReflection->getDocComment();
            $methodReflectionData['param_name_list'] = $this->_formatParamNameList($methodReflection->getParameters());
        } catch (Exception $e) {
        }

        return $methodReflectionData;
    }

    private function _formatParamNameList($params) {
        $paramNameList = [];
        if (!$params) {
            return [];
        }

        foreach ($params as $_k => $_obj) {
            $paramNameList[$_k] = $_obj->name;
        }

        return $paramNameList;
    }

    private function _interpretMethodDocument($document) {
        $documentRules = [];
        $interpret = explode("\n", $document);

        if (!$interpret) {
            return $documentRules;
        }

        foreach ($interpret as $_rule) {
            $_flagStartPos = strpos($_rule, '@');
            if ($_flagStartPos === FALSE) {
                continue;
            }

            $_flagStartPos += 1;
            $_flagEndPos = strpos($_rule, '(', $_flagStartPos);
            if ($_flagEndPos === FALSE) {
                continue;
            }

            $_paramRuleStartPos = $_flagEndPos + 1;
            $_paramRuleEndPos = strpos($_rule, ')', $_paramRuleStartPos);
            if ($_paramRuleEndPos === FALSE) {
                continue;
            }

            $_paramRule = substr($_rule, $_paramRuleStartPos, $_paramRuleEndPos - $_paramRuleStartPos);
            $interpretedRules = $this->_interpretParamRule($_paramRule);
            if (!$interpretedRules) {
                continue;
            }

            $_flag = substr($_rule, $_flagStartPos, $_flagEndPos - $_flagStartPos);

            if (isset($documentRules[$_flag])) {
                $documentRules[$_flag][] = $interpretedRules;
            } else {
                $documentRules[$_flag] = [$interpretedRules];
            }
        }

        return $documentRules;
    }

    private function _interpretParamRule($paramRule) {
        $interpretedRules = [];
        if (!$paramRule) {
            return $interpretedRules;
        }

        $paramRuleArray = explode(',', $paramRule);

        switch (count($paramRuleArray)) {
            case 2:
                list($abstract, $method) = array_map('trim', $paramRuleArray);
                $interpretedRules = ['abstract' => $abstract, 'method' => $method, 'param_rule' => ''];
                break;

            case 3:
                list($abstract, $method, $param) = array_map('trim', $paramRuleArray);
                $interpretedRules = ['abstract' => $abstract, 'method' => $method, 'param_rule' => $param];
                break;
        }

        return $interpretedRules;
    }
}